import logger from '../core/logger';
import apiInfo from './core/apiInfo';
import current from '../core/current';
import hots from '../model/videos/hots';
import apiProvider from './core/apiProvider';
import { clientBase } from './core/clientBase';
import dashModel from '../model/videos/dashModel';
import settingHelper from '../core/settingHelper';
import returnModel from '../model/common/returnModel';
import qualityInfo from '../model/videos/qualityInfo';
import videoUrlInfo from '../model/videos/videoUrlInfo';
import homeVideoModel from '../model/videos/homeVideoModel';
import { tagsModel } from '../model/videos/videoInfoModels';
import interactionEdgeInfo from '../model/videos/interactionEdgeInfo';

class videoClient extends clientBase {
  constructor() {
    super();
  }

  getTags(id: number): Promise<returnModel<tagsModel>> {
    return new Promise((resolve) => {
      try {
        let rnd = Math.floor((Math.random() * 100) + 1);
        let url = `http://api.bilibili.com/x/tag/hots?rid=${id}&type=0&jsonp=json?rnd=${rnd}`;
        this.client.getResult(url).then((res) => {
          if (res.code == 0) {
            let data: tagsModel = res;
            resolve(this.buildSuccessResult<tagsModel>(data));
          } else
            resolve(this.buildFailedResult<tagsModel>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(this.buildExceptionResult<tagsModel>(e));
      }
    });
  }

  getHot(pageIndex: number, last_param: string): Promise<returnModel<hots>> {
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://app.bilibili.com/x/v2/show/popular/index",
          `&fnval=16&fnver=0&force_host=0&fourk=1&idx=${pageIndex}&last_param=${last_param}&qn=32`);
        this.client.getResult(info).then((res) => {
          if (res.code == 0) {
            let data: hots = res;
            resolve(this.buildSuccessResult<hots>(data));
          } else
            resolve(this.buildFailedResult<hots>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(this.buildExceptionResult<hots>(e));
      }
    });
  }

  getRecommend(currentPage: string): Promise<returnModel<homeVideoModel>> {
    return new Promise((resolve) => {
      try {
        let pull = (currentPage == "0").toString().toLowerCase();
        let info = new apiInfo("https://app.bilibili.com/x/v2/feed/index",
          `&flush=0&idx=${currentPage}&login_event=2&network=wifi&open_event=&pull=${pull}&qn=32&style=2`, true);
        this.client.getResult(info).then((res) => {
          if (res.code == 0) {
            let data: homeVideoModel = res;
            resolve(this.buildSuccessResult<homeVideoModel>(data));
          } else
            resolve(this.buildFailedResult<homeVideoModel>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(this.buildExceptionResult<homeVideoModel>(e));
      }
    });
  }

  getAnimeQualities(mid: number, seasonType: number): Promise<returnModel<Array<qualityInfo>>> {
    let qualities = [];
    return new Promise((resolve) => {
      try {
        let info = new apiInfo(`https://api.bilibili.com/pgc/player/web/playurl?cid=${mid}&otype=json&type=&quality=64&module=bangumi&season_type=${seasonType}`,
          settingHelper.useDASH ? "&fourk=1&fnver=0&fnval=16" : '', true);
        this.client.getResult(info, apiProvider.WebVideoKey).then((res) => {
          if (res.code == 0) {
            let dash: dashModel = res.result;
            for (let item of dash.accept_description) {
              let qn = dash.accept_quality[dash.accept_description.indexOf(item)];
              if ((current.instance.isLogin || parseInt(item) <= 32)
              && (current.instance.isVip || parseInt(item) >= 74))
                qualities.push(new qualityInfo(qn, item));
            }
          } else
            qualities = this.getDefault();
          resolve(this.buildSuccessResult<Array<qualityInfo>>(qualities));
        });
      } catch (e) {
        logger.error(e);
        resolve(this.buildExceptionResult<Array<qualityInfo>>(e));
      }
    });
  }

  getVideoQualities(aid: string, cid: number): Promise<returnModel<Array<qualityInfo>>> {
    let qualities = [];
    return new Promise((resolve) => {
      try {
        let info = new apiInfo(`https://api.bilibili.com/x/player/playurl?avid=${aid}&cid=${cid}&qn=64&type=&otype=json`,
          settingHelper.useDASH ? "&fourk=1&fnver=0&fnval=16" : '', true);
        this.client.getResult(info, apiProvider.AndroidVideoKey).then((res) => {
          let data: videoUrlInfo = res;
          if (data.code == 0) {
            if (current.instance.isLogin) {
              for (let i = 0; i < data.data.accept_quality.length; i++)
                qualities.push(new qualityInfo(data.data.accept_quality[i], data.data.accept_description[i], data.data.dash));
            } else
              qualities = this.getDefault();
            resolve(this.buildSuccessResult<Array<qualityInfo>>(qualities));
          }
          else
            resolve(this.buildFailedResult<Array<qualityInfo>>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(this.buildExceptionResult<Array<qualityInfo>>(e));
      }
    });
  }

  interactionInfo(aid: string, graphVer: number, edgeId: number): Promise<returnModel<interactionEdgeInfo>> {
    return new Promise((resolve) => {
      try {
        let info = new apiInfo(`https://api.bilibili.com/x/stein/edgeinfo_v2`, `&aid=${aid}&graph_version=${graphVer}&edge_id=${edgeId}`, true);
        this.client.getResult(info).then((res) => {
          if (res.code == 0) {
            let data: interactionEdgeInfo = res.data;
            resolve(this.buildSuccessResult<interactionEdgeInfo>(data));
          }
          else
            resolve(this.buildFailedResult<interactionEdgeInfo>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(this.buildExceptionResult<interactionEdgeInfo>(e));
      }
    });
  }

  private getDefault(): Array<qualityInfo> {
    let qualities = [];
    if (current.instance.isLogin) {
      qualities.push(new qualityInfo(16, "流畅"));
      qualities.push(new qualityInfo(32, "清晰"));
      qualities.push(new qualityInfo(64, "高清"));
      qualities.push(new qualityInfo(80, "超清"));
    } else {
      qualities.push(new qualityInfo(16, "流畅(登录享受更多清晰度)"));
      qualities.push(new qualityInfo(32, "清晰(登录享受更多清晰度)"));
    }
    return qualities;
  }
}
export default new videoClient();